﻿using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System;

namespace Waaahsabi.Controls.DWM
{
	public class Desktop
	{
		private Stack<TheGameWindow> _windowList;
		private readonly Canvas _desktop;
		private readonly Taskbar _taskbar;

		private double _currentWindowCreationPosition;

		public Desktop(Canvas parentCanvas, Taskbar taskBar)
		{
			_windowList = new Stack<TheGameWindow>();
			_desktop = parentCanvas;
			if (taskBar != null)
			{
				_taskbar = taskBar;
				taskBar.ItemClicked += TaskBarItemClicked;
			}
		}

		void TaskBarItemClicked(object sender, TaskBarEventArgs e)
		{
			TheGameWindow wnd = (from i in _windowList where i.WindowId == e.Item.ItemId select i).FirstOrDefault();
			if(wnd == null)
				return;
			switch (wnd.WindowState)
			{
				case WindowState.Minimized:
					wnd.Restore();
					BringWindowToTop(wnd);
					break;
				case WindowState.Maximized:
					wnd.Restore();
					BringWindowToTop(wnd);
					break;
				case WindowState.Normal:
					if (wnd.IsFocused)
					{
						wnd.Minimize();
						wnd.IsFocused = false;
						TheGameWindow previous;
						if(TryGetPreviousWindow(wnd, out previous))
							previous.IsFocused = true;
					}
					else
						BringWindowToTop(wnd);
					break;
			}
			//if (wnd.WindowState == WindowState.Minimized)
			//    wnd.Restore();
			//else
			//    wnd.Minimize();
		}

		private bool TryGetPreviousWindow(TheGameWindow wnd, out TheGameWindow previous)
		{
			previous = null;
			List<TheGameWindow> list = new List<TheGameWindow>(_windowList.Reverse());
			int thisIdx = list.IndexOf(wnd);
			thisIdx--;
			if (thisIdx < 0)
				return false;
			previous = list[thisIdx];
			return true;
		}

		public TheGameWindow CreateWindow(string windowTitle, UIElement content)
		{
			TheGameWindow wnd = new TheGameWindow(Guid.NewGuid());
			wnd.WindowTitle = windowTitle;
			wnd.Content = content;
			wnd.OnFocus += wnd_OnFocus;
			wnd.OnClosing += wnd_OnClosing;
			wnd.OnClosed += wnd_OnClosed;
			wnd.AllowClose = true;
			_windowList.Push(wnd);
			if (_taskbar != null)
			{
				_taskbar.Items.Add(new TaskBarItem {ItemId = wnd.WindowId, ItemName = wnd.WindowTitle});
			}

			wnd.OnShowRequested += (s, e) =>
			{
				TheGameWindow w = s as TheGameWindow;
				if(w != null && !_desktop.Children.Contains(w))
					_desktop.Children.Add(w);
				//Canvas.SetZIndex(w, 2000);
				Canvas.SetLeft(w, _currentWindowCreationPosition);
				Canvas.SetTop(w, _currentWindowCreationPosition);
				_currentWindowCreationPosition += 32;
				if (_currentWindowCreationPosition > 320
					//(currentWindowCreationPosition > content.RenderSize.Height - w.Height) || 
					//(currentWindowCreationPosition > content.RenderSize.Width - w.Width)
				)
					_currentWindowCreationPosition = 0;
			};
			BringWindowToTop(wnd);
			//Window win = new Window();
			return wnd;
		}

		void wnd_OnClosed(object sender, RoutedEventArgs e)
		{
			if(!(sender is TheGameWindow))
				return;
			TheGameWindow w = sender as TheGameWindow;
			_desktop.Children.Remove(w);
			BringWindowToTop(w);
			_windowList.Pop();
			if (_taskbar != null)
			{
				TaskBarItem tbi = (from i in _taskbar.Items where i.ItemId == w.WindowId select i).FirstOrDefault();
				if (tbi != null)
					_taskbar.Items.Remove(tbi);
			}
		}

		void wnd_OnClosing(object sender, RoutedEventArgs e)
		{
		}

		void wnd_OnFocus(object sender, RoutedEventArgs e)
		{
			if(!(sender is TheGameWindow))
				return;
			TheGameWindow wnd = sender as TheGameWindow;
			BringWindowToTop(wnd);
		}

		private void BringWindowToTop(TheGameWindow wnd)
		{
			//  1  2 *3 -> 1,2 -> 3,1,2
			//  3 *1  2 -> 3,2 -> 1,3,2
			//  1  3  2

			//create List<> from stack
			//reason for reverse: Stack's "top" item is index 0, List's "top" item is .Last()
			List<TheGameWindow> list = new List<TheGameWindow>(_windowList.Reverse());
			
			
			//remove wnd from within list
			list.Remove(wnd);
			foreach (var item in list)
				item.IsFocused = false;
			//reinitialize stack with contents of list. Note: Here the order of items gets reversed by the constructor.
			_windowList = new Stack<TheGameWindow>(list);
			
			//push wnd to top of stack
			_windowList.Push(wnd);
			wnd.IsFocused = true;
			RebuildZOrder();
		}

		private void RebuildZOrder()
		{
			int zIndex = 0;

			//since stack's "top" item is index 0, we have to go through the list backwards, from bottom to top.
			foreach (TheGameWindow w in _windowList.Reverse())
			{
				Canvas.SetZIndex(w, zIndex++);
			}
		}

		public void ShowWindow(Guid windowId)
		{
			TheGameWindow toShow = _windowList.Where(it => it.WindowId == windowId).FirstOrDefault();
			if(_desktop.Children.Contains(toShow))
				return;
			if(toShow != null)
				_desktop.Children.Add(toShow);
		}
	}
}
